use std::{collections::HashMap, sync::Arc};

use oracle::{pool::Pool, Connection};
use tokio::{runtime, sync::Mutex};

use super::table;

pub const PAGE_SIZE: usize = 500;
pub const SQL_MODE: bool = table::SQL_MODE;

async fn query(conn: &Connection, keys: &Vec<String>, _build_in_users: &Vec<String>) -> Vec<String> {
    let mut stmt;
    if SQL_MODE {
        let sql_text = format!(
            "select username from dba_users where username in ('{}')",
            keys.join("','")
        );
        // println!("{:?}: sql_text: {sql_text}", thread::current().id());
        stmt = conn.statement(&sql_text).build().unwrap();
    } else {
        let placeholders = (1..=keys.len())
            .map(|i| format!(":{}", i))
            .collect::<Vec<String>>()
            .join(",");
        // println!("placeholders: {}", placeholders);
        let sql_text = format!(
            "select username from dba_users where username in ({})",
            placeholders
        );
        // println!("{:?}: sql_text: {sql_text}", thread::current().id());
        stmt = conn.statement(&sql_text).build().unwrap();
        for (idx, key) in keys.iter().enumerate() {
            stmt.bind(idx + 1, key).unwrap();
        }
    }

    // println!("SQL: {}", sql);
    let mut users = vec![];
    let rows = stmt.query_as::<String>(&[]).unwrap();
    for row_result in rows {
        let row_result = row_result.unwrap();
        // if build_in_users.contains(&row_result) {
        //     println!("--- Build-in User: {}", row_result);
        //     continue;
        // }
        users.push(row_result);
    }
    users
}

pub async fn query_users(
    pool: &Pool,
    tables: &HashMap<String, Vec<String>>,
    build_in_users: &Vec<String>,
    page_size: usize,
) -> Vec<String> {
    let mut db_users: Vec<String> = Vec::new();
    // println!("{} USER {}", "-".repeat(15), "-".repeat(15));
    let mut user_list: Vec<String> = tables.clone().into_keys().collect();
    // 启用多线程
    let user_list_count = user_list.len();
    let mut handles = vec![];
    let page_count = user_list_count / page_size
        + if user_list_count % page_size == 0 {
            0
        } else {
            1
        };
    // println!("page_count: {}", page_count);
    let page = Arc::new(Mutex::new(page_count));
    // 创建线程池
    let rt = runtime::Builder::new_multi_thread()
        .worker_threads(4)
        .enable_io()
        .enable_time()
        .build()
        .unwrap();

    loop {
        let mut lock = page.lock().await;
        let current_page: usize = lock.to_string().parse().unwrap();
        *lock -= 1;

        let mut cloned_user_list = user_list.clone();
        user_list = cloned_user_list.split_off(if cloned_user_list.len() > page_size {
            page_size
        } else {
            cloned_user_list.len()
        });

        let conn = pool.get().unwrap();
        let cloned_build_in_users = build_in_users.clone();
        let handle =
            rt.spawn(async move { query(&conn, &cloned_user_list, &cloned_build_in_users).await });
        handles.push(handle);

        if current_page <= 1 {
            break;
        }
    }

    for handle in handles {
        let mut users = handle.await.unwrap();
        db_users.append(&mut users);
    }
    rt.shutdown_background();

    // for owner in tables.keys() {
    //     if pos > page_size {
    //         query(conn, &keys, &mut db_users);

    //         keys.clear();
    //         values.clear();
    //         pos = 1;
    //         continue;
    //     }
    //     pos += 1;
    //     keys.push(format!("'{}'", owner.to_string()));
    // }

    // if keys.len() > 0 {
    //     query(conn, &keys, &mut db_users);
    // }

    db_users
}
